package p.ithorns.sample.minio.utils;


import org.apache.commons.codec.digest.Blake3;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.regex.Matcher;

/**
 * FileUtil
 *
 * @author liuhaitao
 * @date 2024/4/7 14:50
 * @since
 */
public class FileUtil {

    private final static String CHARSET = "UTF-8";

    private static final String ROOT_DIR = System.getProperty("user.dir");

    private static final String SEPARATOR = System.getProperty("file.separator");

    public static File createFile(String filePath) {
        Path absPath = getAbsPath(filePath);
        File file = absPath.toFile();

        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdir();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return file;
    }


    /**
     * 获取指定相对路径在当前项目下的绝对路径
     *
     * @param path -相对路径
     * @return Path 当前项目下的绝对路径
     */
    public static Path getAbsPath(String path) {
        // 1. Spring下可使用这个方法  ResourceUtils.getURL(path).getPath(). 区别：尾缀是否带"/"
        return Paths.get(path).toAbsolutePath().normalize();
    }

    public static String getAbsPathUri(String path) {
        return "file:"
                + ROOT_DIR
                + SEPARATOR
                + StringUtil.replaceAll(path, "\\/", Matcher.quoteReplacement(SEPARATOR))
                + SEPARATOR;
    }

    public static String getFilePath(String path) {
        return ROOT_DIR
                + SEPARATOR
                + StringUtil.replaceAll(path, "\\/", Matcher.quoteReplacement(SEPARATOR));
    }


    public static String getBlake3(InputStream stream) {
        byte[] bytes = read(stream);
        return getBlake3(bytes);
    }

    public static String getBlake3(byte[] bytes) {
        // commons-codec实现
        byte[] hash = new byte[16];
        Blake3.initHash().update(bytes).doFinalize(hash);
        return bytesToHex(hash);

        // org.bouncycastle.crypto.digests.Blake3Digest 实现
//            Blake3Digest digest = new Blake3Digest();
//            digest.update(bytes, 0, bytes.length);
//            byte[] hash = new byte[digest.getDigestSize()];
//            digest.doFinal(hash, 0);
//            return bytesToHex(hash);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }


    private static byte[] read(InputStream is) {
        try (ByteArrayOutputStream os = new ByteArrayOutputStream();) {
            byte[] buffer = new byte[4096];
            int length;
            while ((length = is.read(buffer)) != -1) {
                os.write(buffer, 0, length);
            }
            os.flush();
            return os.toByteArray();
        } catch (Exception e) {
            // return new byte[0];
            throw new RuntimeException("读取流数据失败.", e);
        }
    }

    public static String md5(byte[] bytes, byte[] salt) throws NoSuchAlgorithmException {
        // 确定计算方法
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        if (salt != null && salt.length != 0) {
            md5.update(salt);
        }
        Base64.Encoder base64Encoder = Base64.getEncoder();
        // 加密字符串
        return base64Encoder.encodeToString(md5.digest(bytes));
    }

    public static String md5(String src, String salt) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (src == null || "".equals(src)) {
            return null;
        }
        if (salt == null || "".equals(salt)) {
            return md5(src.getBytes(CHARSET), null);
        }
        return md5(src.getBytes(CHARSET), salt.getBytes(CHARSET));
    }

}